home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyo (Python 2.4)
-
- import imp
- import os
- import marshal
- import struct
- import sys
- import types
- from cStringIO import StringIO
- from compiler import ast, parse, walk, syntax
- from compiler import pyassem, misc, future, symbols
- from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
- from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
- from compiler.pyassem import TupleArg
-
- try:
- VERSION = sys.version_info[0]
- except AttributeError:
- VERSION = 1
-
- callfunc_opcode_info = {
- (0, 0): 'CALL_FUNCTION',
- (1, 0): 'CALL_FUNCTION_VAR',
- (0, 1): 'CALL_FUNCTION_KW',
- (1, 1): 'CALL_FUNCTION_VAR_KW' }
- LOOP = 1
- EXCEPT = 2
- TRY_FINALLY = 3
- END_FINALLY = 4
-
- def compileFile(filename, display = 0):
- f = open(filename, 'U')
- buf = f.read()
- f.close()
- mod = Module(buf, filename)
-
- try:
- mod.compile(display)
- except SyntaxError:
- raise
-
- f = open(filename + 'c', 'wb')
- mod.dump(f)
- f.close()
-
-
- def compile(source, filename, mode, flags = None, dont_inherit = None):
- '''Replacement for builtin compile() function'''
- if flags is not None or dont_inherit is not None:
- raise RuntimeError, 'not implemented yet'
-
- if mode == 'single':
- gen = Interactive(source, filename)
- elif mode == 'exec':
- gen = Module(source, filename)
- elif mode == 'eval':
- gen = Expression(source, filename)
- else:
- raise ValueError("compile() 3rd arg must be 'exec' or 'eval' or 'single'")
- gen.compile()
- return gen.code
-
-
- class AbstractCompileMode:
- mode = None
-
- def __init__(self, source, filename):
- self.source = source
- self.filename = filename
- self.code = None
-
-
- def _get_tree(self):
- tree = parse(self.source, self.mode)
- misc.set_filename(self.filename, tree)
- syntax.check(tree)
- return tree
-
-
- def compile(self):
- pass
-
-
- def getCode(self):
- return self.code
-
-
-
- class Expression(AbstractCompileMode):
- mode = 'eval'
-
- def compile(self):
- tree = self._get_tree()
- gen = ExpressionCodeGenerator(tree)
- self.code = gen.getCode()
-
-
-
- class Interactive(AbstractCompileMode):
- mode = 'single'
-
- def compile(self):
- tree = self._get_tree()
- gen = InteractiveCodeGenerator(tree)
- self.code = gen.getCode()
-
-
-
- class Module(AbstractCompileMode):
- mode = 'exec'
-
- def compile(self, display = 0):
- tree = self._get_tree()
- gen = ModuleCodeGenerator(tree)
- if display:
- import pprint
- print pprint.pprint(tree)
-
- self.code = gen.getCode()
-
-
- def dump(self, f):
- f.write(self.getPycHeader())
- marshal.dump(self.code, f)
-
- MAGIC = imp.get_magic()
-
- def getPycHeader(self):
- mtime = os.path.getmtime(self.filename)
- mtime = struct.pack('<i', mtime)
- return self.MAGIC + mtime
-
-
-
- class LocalNameFinder:
- '''Find local names in scope'''
-
- def __init__(self, names = ()):
- self.names = misc.Set()
- self.globals = misc.Set()
- for name in names:
- self.names.add(name)
-
-
-
- def getLocals(self):
- for elt in self.globals.elements():
- if self.names.has_elt(elt):
- self.names.remove(elt)
- continue
-
- return self.names
-
-
- def visitDict(self, node):
- pass
-
-
- def visitGlobal(self, node):
- for name in node.names:
- self.globals.add(name)
-
-
-
- def visitFunction(self, node):
- self.names.add(node.name)
-
-
- def visitLambda(self, node):
- pass
-
-
- def visitImport(self, node):
- for name, alias in node.names:
- if not alias:
- pass
- self.names.add(name)
-
-
-
- def visitFrom(self, node):
- for name, alias in node.names:
- if not alias:
- pass
- self.names.add(name)
-
-
-
- def visitClass(self, node):
- self.names.add(node.name)
-
-
- def visitAssName(self, node):
- self.names.add(node.name)
-
-
-
- def is_constant_false(node):
- if isinstance(node, ast.Const):
- if not node.value:
- return 1
-
-
- return 0
-
-
- class CodeGenerator:
- '''Defines basic code generator for Python bytecode
-
- This class is an abstract base class. Concrete subclasses must
- define an __init__() that defines self.graph and then calls the
- __init__() defined in this class.
-
- The concrete class must also define the class attributes
- NameFinder, FunctionGen, and ClassGen. These attributes can be
- defined in the initClass() method, which is a hook for
- initializing these methods after all the classes have been
- defined.
- '''
- optimized = 0
- __initialized = None
- class_name = None
-
- def __init__(self):
- if self._CodeGenerator__initialized is None:
- self.initClass()
- self.__class__._CodeGenerator__initialized = 1
-
- self.checkClass()
- self.locals = misc.Stack()
- self.setups = misc.Stack()
- self.last_lineno = None
- self._setupGraphDelegation()
- self._div_op = 'BINARY_DIVIDE'
- futures = self.get_module().futures
- for feature in futures:
- if feature == 'division':
- self.graph.setFlag(CO_FUTURE_DIVISION)
- self._div_op = 'BINARY_TRUE_DIVIDE'
- continue
- if feature == 'generators':
- self.graph.setFlag(CO_GENERATOR_ALLOWED)
- continue
-
-
-
- def initClass(self):
- '''This method is called once for each class'''
- pass
-
-
- def checkClass(self):
- '''Verify that class is constructed correctly'''
-
- try:
- pass
- except AssertionError:
- msg = None
- intro = 'Bad class construction for %s' % self.__class__.__name__
- raise AssertionError, intro
-
-
-
- def _setupGraphDelegation(self):
- self.emit = self.graph.emit
- self.newBlock = self.graph.newBlock
- self.startBlock = self.graph.startBlock
- self.nextBlock = self.graph.nextBlock
- self.setDocstring = self.graph.setDocstring
-
-
- def getCode(self):
- '''Return a code object'''
- return self.graph.getCode()
-
-
- def mangle(self, name):
- if self.class_name is not None:
- return misc.mangle(name, self.class_name)
- else:
- return name
-
-
- def parseSymbols(self, tree):
- s = symbols.SymbolVisitor()
- walk(tree, s)
- return s.scopes
-
-
- def get_module(self):
- raise RuntimeError, 'should be implemented by subclasses'
-
-
- def isLocalName(self, name):
- return self.locals.top().has_elt(name)
-
-
- def storeName(self, name):
- self._nameOp('STORE', name)
-
-
- def loadName(self, name):
- self._nameOp('LOAD', name)
-
-
- def delName(self, name):
- self._nameOp('DELETE', name)
-
-
- def _nameOp(self, prefix, name):
- name = self.mangle(name)
- scope = self.scope.check_name(name)
- if scope == SC_LOCAL:
- if not self.optimized:
- self.emit(prefix + '_NAME', name)
- else:
- self.emit(prefix + '_FAST', name)
- elif scope == SC_GLOBAL:
- if not self.optimized:
- self.emit(prefix + '_NAME', name)
- else:
- self.emit(prefix + '_GLOBAL', name)
- elif scope == SC_FREE or scope == SC_CELL:
- self.emit(prefix + '_DEREF', name)
- else:
- raise RuntimeError, 'unsupported scope for var %s: %d' % (name, scope)
-
-
- def _implicitNameOp(self, prefix, name):
- """Emit name ops for names generated implicitly by for loops
-
- The interpreter generates names that start with a period or
- dollar sign. The symbol table ignores these names because
- they aren't present in the program text.
- """
- if self.optimized:
- self.emit(prefix + '_FAST', name)
- else:
- self.emit(prefix + '_NAME', name)
-
-
- def set_lineno(self, node, force = False):
- '''Emit SET_LINENO if necessary.
-
- The instruction is considered necessary if the node has a
- lineno attribute and it is different than the last lineno
- emitted.
-
- Returns true if SET_LINENO was emitted.
-
- There are no rules for when an AST node should have a lineno
- attribute. The transformer and AST code need to be reviewed
- and a consistent policy implemented and documented. Until
- then, this method works around missing line numbers.
- '''
- lineno = getattr(node, 'lineno', None)
- if lineno is not None:
- if lineno != self.last_lineno or force:
- self.emit('SET_LINENO', lineno)
- self.last_lineno = lineno
- return True
-
- return False
-
- NameFinder = LocalNameFinder
- FunctionGen = None
- ClassGen = None
-
- def visitModule(self, node):
- self.scopes = self.parseSymbols(node)
- self.scope = self.scopes[node]
- self.emit('SET_LINENO', 0)
- if node.doc:
- self.emit('LOAD_CONST', node.doc)
- self.storeName('__doc__')
-
- lnf = walk(node.node, self.NameFinder(), verbose = 0)
- self.locals.push(lnf.getLocals())
- self.visit(node.node)
- self.emit('LOAD_CONST', None)
- self.emit('RETURN_VALUE')
-
-
- def visitExpression(self, node):
- self.set_lineno(node)
- self.scopes = self.parseSymbols(node)
- self.scope = self.scopes[node]
- self.visit(node.node)
- self.emit('RETURN_VALUE')
-
-
- def visitFunction(self, node):
- self._visitFuncOrLambda(node, isLambda = 0)
- if node.doc:
- self.setDocstring(node.doc)
-
- self.storeName(node.name)
-
-
- def visitLambda(self, node):
- self._visitFuncOrLambda(node, isLambda = 1)
-
-
- def _visitFuncOrLambda(self, node, isLambda = 0):
- if not isLambda and node.decorators:
- for decorator in node.decorators.nodes:
- self.visit(decorator)
-
- ndecorators = len(node.decorators.nodes)
- else:
- ndecorators = 0
- gen = self.FunctionGen(node, self.scopes, isLambda, self.class_name, self.get_module())
- walk(node.code, gen)
- gen.finish()
- self.set_lineno(node)
- for default in node.defaults:
- self.visit(default)
-
- frees = gen.scope.get_free_vars()
- if frees:
- for name in frees:
- self.emit('LOAD_CLOSURE', name)
-
- self.emit('LOAD_CONST', gen)
- self.emit('MAKE_CLOSURE', len(node.defaults))
- else:
- self.emit('LOAD_CONST', gen)
- self.emit('MAKE_FUNCTION', len(node.defaults))
- for i in range(ndecorators):
- self.emit('CALL_FUNCTION', 1)
-
-
-
- def visitClass(self, node):
- gen = self.ClassGen(node, self.scopes, self.get_module())
- walk(node.code, gen)
- gen.finish()
- self.set_lineno(node)
- self.emit('LOAD_CONST', node.name)
- for base in node.bases:
- self.visit(base)
-
- self.emit('BUILD_TUPLE', len(node.bases))
- frees = gen.scope.get_free_vars()
- for name in frees:
- self.emit('LOAD_CLOSURE', name)
-
- self.emit('LOAD_CONST', gen)
- if frees:
- self.emit('MAKE_CLOSURE', 0)
- else:
- self.emit('MAKE_FUNCTION', 0)
- self.emit('CALL_FUNCTION', 0)
- self.emit('BUILD_CLASS')
- self.storeName(node.name)
-
-
- def visitIf(self, node):
- end = self.newBlock()
- numtests = len(node.tests)
- for i in range(numtests):
- (test, suite) = node.tests[i]
- if is_constant_false(test):
- continue
-
- self.set_lineno(test)
- self.visit(test)
- nextTest = self.newBlock()
- self.emit('JUMP_IF_FALSE', nextTest)
- self.nextBlock()
- self.emit('POP_TOP')
- self.visit(suite)
- self.emit('JUMP_FORWARD', end)
- self.startBlock(nextTest)
- self.emit('POP_TOP')
-
- if node.else_:
- self.visit(node.else_)
-
- self.nextBlock(end)
-
-
- def visitWhile(self, node):
- self.set_lineno(node)
- loop = self.newBlock()
- else_ = self.newBlock()
- after = self.newBlock()
- self.emit('SETUP_LOOP', after)
- self.nextBlock(loop)
- self.setups.push((LOOP, loop))
- self.set_lineno(node, force = True)
- self.visit(node.test)
- if not else_:
- pass
- self.emit('JUMP_IF_FALSE', after)
- self.nextBlock()
- self.emit('POP_TOP')
- self.visit(node.body)
- self.emit('JUMP_ABSOLUTE', loop)
- self.startBlock(else_)
- self.emit('POP_TOP')
- self.emit('POP_BLOCK')
- self.setups.pop()
- if node.else_:
- self.visit(node.else_)
-
- self.nextBlock(after)
-
-
- def visitFor(self, node):
- start = self.newBlock()
- anchor = self.newBlock()
- after = self.newBlock()
- self.setups.push((LOOP, start))
- self.set_lineno(node)
- self.emit('SETUP_LOOP', after)
- self.visit(node.list)
- self.emit('GET_ITER')
- self.nextBlock(start)
- self.set_lineno(node, force = 1)
- self.emit('FOR_ITER', anchor)
- self.visit(node.assign)
- self.visit(node.body)
- self.emit('JUMP_ABSOLUTE', start)
- self.nextBlock(anchor)
- self.emit('POP_BLOCK')
- self.setups.pop()
- if node.else_:
- self.visit(node.else_)
-
- self.nextBlock(after)
-
-
- def visitBreak(self, node):
- if not self.setups:
- raise SyntaxError, "'break' outside loop (%s, %d)" % (node.filename, node.lineno)
-
- self.set_lineno(node)
- self.emit('BREAK_LOOP')
-
-
- def visitContinue(self, node):
- if not self.setups:
- raise SyntaxError, "'continue' outside loop (%s, %d)" % (node.filename, node.lineno)
-
- (kind, block) = self.setups.top()
- if kind == LOOP:
- self.set_lineno(node)
- self.emit('JUMP_ABSOLUTE', block)
- self.nextBlock()
- elif kind == EXCEPT or kind == TRY_FINALLY:
- self.set_lineno(node)
- top = len(self.setups)
- while top > 0:
- top = top - 1
- (kind, loop_block) = self.setups[top]
- if kind == LOOP:
- break
- continue
- if kind != LOOP:
- raise SyntaxError, "'continue' outside loop (%s, %d)" % (node.filename, node.lineno)
-
- self.emit('CONTINUE_LOOP', loop_block)
- self.nextBlock()
- elif kind == END_FINALLY:
- msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
- raise SyntaxError, msg % (node.filename, node.lineno)
-
-
-
- def visitTest(self, node, jump):
- end = self.newBlock()
- for child in node.nodes[:-1]:
- self.visit(child)
- self.emit(jump, end)
- self.nextBlock()
- self.emit('POP_TOP')
-
- self.visit(node.nodes[-1])
- self.nextBlock(end)
-
-
- def visitAnd(self, node):
- self.visitTest(node, 'JUMP_IF_FALSE')
-
-
- def visitOr(self, node):
- self.visitTest(node, 'JUMP_IF_TRUE')
-
-
- def visitCompare(self, node):
- self.visit(node.expr)
- cleanup = self.newBlock()
- for op, code in node.ops[:-1]:
- self.visit(code)
- self.emit('DUP_TOP')
- self.emit('ROT_THREE')
- self.emit('COMPARE_OP', op)
- self.emit('JUMP_IF_FALSE', cleanup)
- self.nextBlock()
- self.emit('POP_TOP')
-
- if node.ops:
- (op, code) = node.ops[-1]
- self.visit(code)
- self.emit('COMPARE_OP', op)
-
- if len(node.ops) > 1:
- end = self.newBlock()
- self.emit('JUMP_FORWARD', end)
- self.startBlock(cleanup)
- self.emit('ROT_TWO')
- self.emit('POP_TOP')
- self.nextBlock(end)
-
-
- __list_count = 0
-
- def visitListComp(self, node):
- self.set_lineno(node)
- append = '$append%d' % self._CodeGenerator__list_count
- self._CodeGenerator__list_count = self._CodeGenerator__list_count + 1
- self.emit('BUILD_LIST', 0)
- self.emit('DUP_TOP')
- self.emit('LOAD_ATTR', 'append')
- self._implicitNameOp('STORE', append)
- stack = []
- for i, for_ in zip(range(len(node.quals)), node.quals):
- (start, anchor) = self.visit(for_)
- cont = None
- for if_ in for_.ifs:
- if cont is None:
- cont = self.newBlock()
-
- self.visit(if_, cont)
-
- stack.insert(0, (start, cont, anchor))
-
- self._implicitNameOp('LOAD', append)
- self.visit(node.expr)
- self.emit('CALL_FUNCTION', 1)
- self.emit('POP_TOP')
- for start, cont, anchor in stack:
- if cont:
- skip_one = self.newBlock()
- self.emit('JUMP_FORWARD', skip_one)
- self.startBlock(cont)
- self.emit('POP_TOP')
- self.nextBlock(skip_one)
-
- self.emit('JUMP_ABSOLUTE', start)
- self.startBlock(anchor)
-
- self._implicitNameOp('DELETE', append)
- self._CodeGenerator__list_count = self._CodeGenerator__list_count - 1
-
-
- def visitListCompFor(self, node):
- start = self.newBlock()
- anchor = self.newBlock()
- self.visit(node.list)
- self.emit('GET_ITER')
- self.nextBlock(start)
- self.set_lineno(node, force = True)
- self.emit('FOR_ITER', anchor)
- self.nextBlock()
- self.visit(node.assign)
- return (start, anchor)
-
-
- def visitListCompIf(self, node, branch):
- self.set_lineno(node, force = True)
- self.visit(node.test)
- self.emit('JUMP_IF_FALSE', branch)
- self.newBlock()
- self.emit('POP_TOP')
-
-
- def visitGenExpr(self, node):
- gen = GenExprCodeGenerator(node, self.scopes, self.class_name, self.get_module())
- walk(node.code, gen)
- gen.finish()
- self.set_lineno(node)
- frees = gen.scope.get_free_vars()
- if frees:
- for name in frees:
- self.emit('LOAD_CLOSURE', name)
-
- self.emit('LOAD_CONST', gen)
- self.emit('MAKE_CLOSURE', 0)
- else:
- self.emit('LOAD_CONST', gen)
- self.emit('MAKE_FUNCTION', 0)
- self.visit(node.code.quals[0].iter)
- self.emit('GET_ITER')
- self.emit('CALL_FUNCTION', 1)
-
-
- def visitGenExprInner(self, node):
- self.set_lineno(node)
- stack = []
- for i, for_ in zip(range(len(node.quals)), node.quals):
- (start, anchor) = self.visit(for_)
- cont = None
- for if_ in for_.ifs:
- if cont is None:
- cont = self.newBlock()
-
- self.visit(if_, cont)
-
- stack.insert(0, (start, cont, anchor))
-
- self.visit(node.expr)
- self.emit('YIELD_VALUE')
- for start, cont, anchor in stack:
- if cont:
- skip_one = self.newBlock()
- self.emit('JUMP_FORWARD', skip_one)
- self.startBlock(cont)
- self.emit('POP_TOP')
- self.nextBlock(skip_one)
-
- self.emit('JUMP_ABSOLUTE', start)
- self.startBlock(anchor)
-
- self.emit('LOAD_CONST', None)
-
-
- def visitGenExprFor(self, node):
- start = self.newBlock()
- anchor = self.newBlock()
- if node.is_outmost:
- self.loadName('[outmost-iterable]')
- else:
- self.visit(node.iter)
- self.emit('GET_ITER')
- self.nextBlock(start)
- self.set_lineno(node, force = True)
- self.emit('FOR_ITER', anchor)
- self.nextBlock()
- self.visit(node.assign)
- return (start, anchor)
-
-
- def visitGenExprIf(self, node, branch):
- self.set_lineno(node, force = True)
- self.visit(node.test)
- self.emit('JUMP_IF_FALSE', branch)
- self.newBlock()
- self.emit('POP_TOP')
-
-
- def visitAssert(self, node):
- pass
-
-
- def visitRaise(self, node):
- self.set_lineno(node)
- n = 0
- if node.expr1:
- self.visit(node.expr1)
- n = n + 1
-
- if node.expr2:
- self.visit(node.expr2)
- n = n + 1
-
- if node.expr3:
- self.visit(node.expr3)
- n = n + 1
-
- self.emit('RAISE_VARARGS', n)
-
-
- def visitTryExcept(self, node):
- body = self.newBlock()
- handlers = self.newBlock()
- end = self.newBlock()
- if node.else_:
- lElse = self.newBlock()
- else:
- lElse = end
- self.set_lineno(node)
- self.emit('SETUP_EXCEPT', handlers)
- self.nextBlock(body)
- self.setups.push((EXCEPT, body))
- self.visit(node.body)
- self.emit('POP_BLOCK')
- self.setups.pop()
- self.emit('JUMP_FORWARD', lElse)
- self.startBlock(handlers)
- last = len(node.handlers) - 1
- for i in range(len(node.handlers)):
- (expr, target, body) = node.handlers[i]
- self.set_lineno(expr)
- if expr:
- self.emit('DUP_TOP')
- self.visit(expr)
- self.emit('COMPARE_OP', 'exception match')
- next = self.newBlock()
- self.emit('JUMP_IF_FALSE', next)
- self.nextBlock()
- self.emit('POP_TOP')
-
- self.emit('POP_TOP')
- if target:
- self.visit(target)
- else:
- self.emit('POP_TOP')
- self.emit('POP_TOP')
- self.visit(body)
- self.emit('JUMP_FORWARD', end)
- if expr:
- self.nextBlock(next)
- else:
- self.nextBlock()
- if expr:
- self.emit('POP_TOP')
- continue
-
- self.emit('END_FINALLY')
- if node.else_:
- self.nextBlock(lElse)
- self.visit(node.else_)
-
- self.nextBlock(end)
-
-
- def visitTryFinally(self, node):
- body = self.newBlock()
- final = self.newBlock()
- self.set_lineno(node)
- self.emit('SETUP_FINALLY', final)
- self.nextBlock(body)
- self.setups.push((TRY_FINALLY, body))
- self.visit(node.body)
- self.emit('POP_BLOCK')
- self.setups.pop()
- self.emit('LOAD_CONST', None)
- self.nextBlock(final)
- self.setups.push((END_FINALLY, final))
- self.visit(node.final)
- self.emit('END_FINALLY')
- self.setups.pop()
-
-
- def visitDiscard(self, node):
- self.set_lineno(node)
- self.visit(node.expr)
- self.emit('POP_TOP')
-
-
- def visitConst(self, node):
- self.emit('LOAD_CONST', node.value)
-
-
- def visitKeyword(self, node):
- self.emit('LOAD_CONST', node.name)
- self.visit(node.expr)
-
-
- def visitGlobal(self, node):
- pass
-
-
- def visitName(self, node):
- self.set_lineno(node)
- self.loadName(node.name)
-
-
- def visitPass(self, node):
- self.set_lineno(node)
-
-
- def visitImport(self, node):
- self.set_lineno(node)
- for name, alias in node.names:
- if VERSION > 1:
- self.emit('LOAD_CONST', None)
-
- self.emit('IMPORT_NAME', name)
- mod = name.split('.')[0]
- if alias:
- self._resolveDots(name)
- self.storeName(alias)
- continue
- self.storeName(mod)
-
-
-
- def visitFrom(self, node):
- self.set_lineno(node)
- fromlist = map((lambda .0: (name, alias) = .0name), node.names)
- if VERSION > 1:
- self.emit('LOAD_CONST', tuple(fromlist))
-
- self.emit('IMPORT_NAME', node.modname)
- for name, alias in node.names:
- if VERSION > 1:
- if name == '*':
- self.namespace = 0
- self.emit('IMPORT_STAR')
- return None
- else:
- self.emit('IMPORT_FROM', name)
- self._resolveDots(name)
- if not alias:
- pass
- self.storeName(name)
- name == '*'
- self.emit('IMPORT_FROM', name)
-
- self.emit('POP_TOP')
-
-
- def _resolveDots(self, name):
- elts = name.split('.')
- if len(elts) == 1:
- return None
-
- for elt in elts[1:]:
- self.emit('LOAD_ATTR', elt)
-
-
-
- def visitGetattr(self, node):
- self.visit(node.expr)
- self.emit('LOAD_ATTR', self.mangle(node.attrname))
-
-
- def visitAssign(self, node):
- self.set_lineno(node)
- self.visit(node.expr)
- dups = len(node.nodes) - 1
- for i in range(len(node.nodes)):
- elt = node.nodes[i]
- if i < dups:
- self.emit('DUP_TOP')
-
- if isinstance(elt, ast.Node):
- self.visit(elt)
- continue
-
-
-
- def visitAssName(self, node):
- if node.flags == 'OP_ASSIGN':
- self.storeName(node.name)
- elif node.flags == 'OP_DELETE':
- self.set_lineno(node)
- self.delName(node.name)
- else:
- print 'oops', node.flags
-
-
- def visitAssAttr(self, node):
- self.visit(node.expr)
- if node.flags == 'OP_ASSIGN':
- self.emit('STORE_ATTR', self.mangle(node.attrname))
- elif node.flags == 'OP_DELETE':
- self.emit('DELETE_ATTR', self.mangle(node.attrname))
- else:
- print 'warning: unexpected flags:', node.flags
- print node
-
-
- def _visitAssSequence(self, node, op = 'UNPACK_SEQUENCE'):
- if findOp(node) != 'OP_DELETE':
- self.emit(op, len(node.nodes))
-
- for child in node.nodes:
- self.visit(child)
-
-
- if VERSION > 1:
- visitAssTuple = _visitAssSequence
- visitAssList = _visitAssSequence
- else:
-
- def visitAssTuple(self, node):
- self._visitAssSequence(node, 'UNPACK_TUPLE')
-
-
- def visitAssList(self, node):
- self._visitAssSequence(node, 'UNPACK_LIST')
-
-
- def visitAugAssign(self, node):
- self.set_lineno(node)
- aug_node = wrap_aug(node.node)
- self.visit(aug_node, 'load')
- self.visit(node.expr)
- self.emit(self._augmented_opcode[node.op])
- self.visit(aug_node, 'store')
-
- _augmented_opcode = {
- '+=': 'INPLACE_ADD',
- '-=': 'INPLACE_SUBTRACT',
- '*=': 'INPLACE_MULTIPLY',
- '/=': 'INPLACE_DIVIDE',
- '//=': 'INPLACE_FLOOR_DIVIDE',
- '%=': 'INPLACE_MODULO',
- '**=': 'INPLACE_POWER',
- '>>=': 'INPLACE_RSHIFT',
- '<<=': 'INPLACE_LSHIFT',
- '&=': 'INPLACE_AND',
- '^=': 'INPLACE_XOR',
- '|=': 'INPLACE_OR' }
-
- def visitAugName(self, node, mode):
- if mode == 'load':
- self.loadName(node.name)
- elif mode == 'store':
- self.storeName(node.name)
-
-
-
- def visitAugGetattr(self, node, mode):
- if mode == 'load':
- self.visit(node.expr)
- self.emit('DUP_TOP')
- self.emit('LOAD_ATTR', self.mangle(node.attrname))
- elif mode == 'store':
- self.emit('ROT_TWO')
- self.emit('STORE_ATTR', self.mangle(node.attrname))
-
-
-
- def visitAugSlice(self, node, mode):
- if mode == 'load':
- self.visitSlice(node, 1)
- elif mode == 'store':
- slice = 0
- if node.lower:
- slice = slice | 1
-
- if node.upper:
- slice = slice | 2
-
- if slice == 0:
- self.emit('ROT_TWO')
- elif slice == 3:
- self.emit('ROT_FOUR')
- else:
- self.emit('ROT_THREE')
- self.emit('STORE_SLICE+%d' % slice)
-
-
-
- def visitAugSubscript(self, node, mode):
- if len(node.subs) > 1:
- raise SyntaxError, 'augmented assignment to tuple is not possible'
-
- if mode == 'load':
- self.visitSubscript(node, 1)
- elif mode == 'store':
- self.emit('ROT_THREE')
- self.emit('STORE_SUBSCR')
-
-
-
- def visitExec(self, node):
- self.visit(node.expr)
- if node.locals is None:
- self.emit('LOAD_CONST', None)
- else:
- self.visit(node.locals)
- if node.globals is None:
- self.emit('DUP_TOP')
- else:
- self.visit(node.globals)
- self.emit('EXEC_STMT')
-
-
- def visitCallFunc(self, node):
- pos = 0
- kw = 0
- self.set_lineno(node)
- self.visit(node.node)
- for arg in node.args:
- self.visit(arg)
- if isinstance(arg, ast.Keyword):
- kw = kw + 1
- continue
- pos = pos + 1
-
- if node.star_args is not None:
- self.visit(node.star_args)
-
- if node.dstar_args is not None:
- self.visit(node.dstar_args)
-
- have_star = node.star_args is not None
- have_dstar = node.dstar_args is not None
- opcode = callfunc_opcode_info[(have_star, have_dstar)]
- self.emit(opcode, kw << 8 | pos)
-
-
- def visitPrint(self, node, newline = 0):
- self.set_lineno(node)
- if node.dest:
- self.visit(node.dest)
-
- for child in node.nodes:
- if node.dest:
- self.emit('DUP_TOP')
-
- self.visit(child)
- if node.dest:
- self.emit('ROT_TWO')
- self.emit('PRINT_ITEM_TO')
- continue
- self.emit('PRINT_ITEM')
-
- if node.dest and not newline:
- self.emit('POP_TOP')
-
-
-
- def visitPrintnl(self, node):
- self.visitPrint(node, newline = 1)
- if node.dest:
- self.emit('PRINT_NEWLINE_TO')
- else:
- self.emit('PRINT_NEWLINE')
-
-
- def visitReturn(self, node):
- self.set_lineno(node)
- self.visit(node.value)
- self.emit('RETURN_VALUE')
-
-
- def visitYield(self, node):
- self.set_lineno(node)
- self.visit(node.value)
- self.emit('YIELD_VALUE')
-
-
- def visitSlice(self, node, aug_flag = None):
- self.visit(node.expr)
- slice = 0
- if node.lower:
- self.visit(node.lower)
- slice = slice | 1
-
- if node.upper:
- self.visit(node.upper)
- slice = slice | 2
-
- if aug_flag:
- if slice == 0:
- self.emit('DUP_TOP')
- elif slice == 3:
- self.emit('DUP_TOPX', 3)
- else:
- self.emit('DUP_TOPX', 2)
-
- if node.flags == 'OP_APPLY':
- self.emit('SLICE+%d' % slice)
- elif node.flags == 'OP_ASSIGN':
- self.emit('STORE_SLICE+%d' % slice)
- elif node.flags == 'OP_DELETE':
- self.emit('DELETE_SLICE+%d' % slice)
- else:
- print 'weird slice', node.flags
- raise
-
-
- def visitSubscript(self, node, aug_flag = None):
- self.visit(node.expr)
- for sub in node.subs:
- self.visit(sub)
-
- if aug_flag:
- self.emit('DUP_TOPX', 2)
-
- if len(node.subs) > 1:
- self.emit('BUILD_TUPLE', len(node.subs))
-
- if node.flags == 'OP_APPLY':
- self.emit('BINARY_SUBSCR')
- elif node.flags == 'OP_ASSIGN':
- self.emit('STORE_SUBSCR')
- elif node.flags == 'OP_DELETE':
- self.emit('DELETE_SUBSCR')
-
-
-
- def binaryOp(self, node, op):
- self.visit(node.left)
- self.visit(node.right)
- self.emit(op)
-
-
- def visitAdd(self, node):
- return self.binaryOp(node, 'BINARY_ADD')
-
-
- def visitSub(self, node):
- return self.binaryOp(node, 'BINARY_SUBTRACT')
-
-
- def visitMul(self, node):
- return self.binaryOp(node, 'BINARY_MULTIPLY')
-
-
- def visitDiv(self, node):
- return self.binaryOp(node, self._div_op)
-
-
- def visitFloorDiv(self, node):
- return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
-
-
- def visitMod(self, node):
- return self.binaryOp(node, 'BINARY_MODULO')
-
-
- def visitPower(self, node):
- return self.binaryOp(node, 'BINARY_POWER')
-
-
- def visitLeftShift(self, node):
- return self.binaryOp(node, 'BINARY_LSHIFT')
-
-
- def visitRightShift(self, node):
- return self.binaryOp(node, 'BINARY_RSHIFT')
-
-
- def unaryOp(self, node, op):
- self.visit(node.expr)
- self.emit(op)
-
-
- def visitInvert(self, node):
- return self.unaryOp(node, 'UNARY_INVERT')
-
-
- def visitUnarySub(self, node):
- return self.unaryOp(node, 'UNARY_NEGATIVE')
-
-
- def visitUnaryAdd(self, node):
- return self.unaryOp(node, 'UNARY_POSITIVE')
-
-
- def visitUnaryInvert(self, node):
- return self.unaryOp(node, 'UNARY_INVERT')
-
-
- def visitNot(self, node):
- return self.unaryOp(node, 'UNARY_NOT')
-
-
- def visitBackquote(self, node):
- return self.unaryOp(node, 'UNARY_CONVERT')
-
-
- def bitOp(self, nodes, op):
- self.visit(nodes[0])
- for node in nodes[1:]:
- self.visit(node)
- self.emit(op)
-
-
-
- def visitBitand(self, node):
- return self.bitOp(node.nodes, 'BINARY_AND')
-
-
- def visitBitor(self, node):
- return self.bitOp(node.nodes, 'BINARY_OR')
-
-
- def visitBitxor(self, node):
- return self.bitOp(node.nodes, 'BINARY_XOR')
-
-
- def visitEllipsis(self, node):
- self.emit('LOAD_CONST', Ellipsis)
-
-
- def visitTuple(self, node):
- self.set_lineno(node)
- for elt in node.nodes:
- self.visit(elt)
-
- self.emit('BUILD_TUPLE', len(node.nodes))
-
-
- def visitList(self, node):
- self.set_lineno(node)
- for elt in node.nodes:
- self.visit(elt)
-
- self.emit('BUILD_LIST', len(node.nodes))
-
-
- def visitSliceobj(self, node):
- for child in node.nodes:
- self.visit(child)
-
- self.emit('BUILD_SLICE', len(node.nodes))
-
-
- def visitDict(self, node):
- self.set_lineno(node)
- self.emit('BUILD_MAP', 0)
- for k, v in node.items:
- self.emit('DUP_TOP')
- self.visit(k)
- self.visit(v)
- self.emit('ROT_THREE')
- self.emit('STORE_SUBSCR')
-
-
-
-
- class NestedScopeMixin:
- '''Defines initClass() for nested scoping (Python 2.2-compatible)'''
-
- def initClass(self):
- self.__class__.NameFinder = LocalNameFinder
- self.__class__.FunctionGen = FunctionCodeGenerator
- self.__class__.ClassGen = ClassCodeGenerator
-
-
-
- class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
- __super_init = CodeGenerator.__init__
- scopes = None
-
- def __init__(self, tree):
- self.graph = pyassem.PyFlowGraph('<module>', tree.filename)
- self.futures = future.find_futures(tree)
- self._ModuleCodeGenerator__super_init()
- walk(tree, self)
-
-
- def get_module(self):
- return self
-
-
-
- class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
- __super_init = CodeGenerator.__init__
- scopes = None
- futures = ()
-
- def __init__(self, tree):
- self.graph = pyassem.PyFlowGraph('<expression>', tree.filename)
- self._ExpressionCodeGenerator__super_init()
- walk(tree, self)
-
-
- def get_module(self):
- return self
-
-
-
- class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
- __super_init = CodeGenerator.__init__
- scopes = None
- futures = ()
-
- def __init__(self, tree):
- self.graph = pyassem.PyFlowGraph('<interactive>', tree.filename)
- self._InteractiveCodeGenerator__super_init()
- self.set_lineno(tree)
- walk(tree, self)
- self.emit('RETURN_VALUE')
-
-
- def get_module(self):
- return self
-
-
- def visitDiscard(self, node):
- self.visit(node.expr)
- self.emit('PRINT_EXPR')
-
-
-
- class AbstractFunctionCode:
- optimized = 1
- lambdaCount = 0
-
- def __init__(self, func, scopes, isLambda, class_name, mod):
- self.class_name = class_name
- self.module = mod
- if isLambda:
- klass = FunctionCodeGenerator
- name = '<lambda.%d>' % klass.lambdaCount
- klass.lambdaCount = klass.lambdaCount + 1
- else:
- name = func.name
- (args, hasTupleArg) = generateArgList(func.argnames)
- self.graph = pyassem.PyFlowGraph(name, func.filename, args, optimized = 1)
- self.isLambda = isLambda
- self.super_init()
- if not isLambda and func.doc:
- self.setDocstring(func.doc)
-
- lnf = walk(func.code, self.NameFinder(args), verbose = 0)
- self.locals.push(lnf.getLocals())
- if func.varargs:
- self.graph.setFlag(CO_VARARGS)
-
- if func.kwargs:
- self.graph.setFlag(CO_VARKEYWORDS)
-
- self.set_lineno(func)
- if hasTupleArg:
- self.generateArgUnpack(func.argnames)
-
-
-
- def get_module(self):
- return self.module
-
-
- def finish(self):
- self.graph.startExitBlock()
- if not self.isLambda:
- self.emit('LOAD_CONST', None)
-
- self.emit('RETURN_VALUE')
-
-
- def generateArgUnpack(self, args):
- for i in range(len(args)):
- arg = args[i]
- if type(arg) == types.TupleType:
- self.emit('LOAD_FAST', '.%d' % i * 2)
- self.unpackSequence(arg)
- continue
-
-
-
- def unpackSequence(self, tup):
- if VERSION > 1:
- self.emit('UNPACK_SEQUENCE', len(tup))
- else:
- self.emit('UNPACK_TUPLE', len(tup))
- for elt in tup:
- if type(elt) == types.TupleType:
- self.unpackSequence(elt)
- continue
- self._nameOp('STORE', elt)
-
-
- unpackTuple = unpackSequence
-
-
- class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode, CodeGenerator):
- super_init = CodeGenerator.__init__
- scopes = None
- __super_init = AbstractFunctionCode.__init__
-
- def __init__(self, func, scopes, isLambda, class_name, mod):
- self.scopes = scopes
- self.scope = scopes[func]
- self._FunctionCodeGenerator__super_init(func, scopes, isLambda, class_name, mod)
- self.graph.setFreeVars(self.scope.get_free_vars())
- self.graph.setCellVars(self.scope.get_cell_vars())
- if self.scope.generator is not None:
- self.graph.setFlag(CO_GENERATOR)
-
-
-
-
- class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode, CodeGenerator):
- super_init = CodeGenerator.__init__
- scopes = None
- __super_init = AbstractFunctionCode.__init__
-
- def __init__(self, gexp, scopes, class_name, mod):
- self.scopes = scopes
- self.scope = scopes[gexp]
- self._GenExprCodeGenerator__super_init(gexp, scopes, 1, class_name, mod)
- self.graph.setFreeVars(self.scope.get_free_vars())
- self.graph.setCellVars(self.scope.get_cell_vars())
- self.graph.setFlag(CO_GENERATOR)
-
-
-
- class AbstractClassCode:
-
- def __init__(self, klass, scopes, module):
- self.class_name = klass.name
- self.module = module
- self.graph = pyassem.PyFlowGraph(klass.name, klass.filename, optimized = 0, klass = 1)
- self.super_init()
- lnf = walk(klass.code, self.NameFinder(), verbose = 0)
- self.locals.push(lnf.getLocals())
- self.graph.setFlag(CO_NEWLOCALS)
- if klass.doc:
- self.setDocstring(klass.doc)
-
-
-
- def get_module(self):
- return self.module
-
-
- def finish(self):
- self.graph.startExitBlock()
- self.emit('LOAD_LOCALS')
- self.emit('RETURN_VALUE')
-
-
-
- class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
- super_init = CodeGenerator.__init__
- scopes = None
- __super_init = AbstractClassCode.__init__
-
- def __init__(self, klass, scopes, module):
- self.scopes = scopes
- self.scope = scopes[klass]
- self._ClassCodeGenerator__super_init(klass, scopes, module)
- self.graph.setFreeVars(self.scope.get_free_vars())
- self.graph.setCellVars(self.scope.get_cell_vars())
- self.set_lineno(klass)
- self.emit('LOAD_GLOBAL', '__name__')
- self.storeName('__module__')
- if klass.doc:
- self.emit('LOAD_CONST', klass.doc)
- self.storeName('__doc__')
-
-
-
-
- def generateArgList(arglist):
- '''Generate an arg list marking TupleArgs'''
- args = []
- extra = []
- count = 0
- for i in range(len(arglist)):
- elt = arglist[i]
- if type(elt) == types.StringType:
- args.append(elt)
- continue
- if type(elt) == types.TupleType:
- args.append(TupleArg(i * 2, elt))
- extra.extend(misc.flatten(elt))
- count = count + 1
- continue
- raise ValueError, 'unexpect argument type:', elt
-
- return (args + extra, count)
-
-
- def findOp(node):
- '''Find the op (DELETE, LOAD, STORE) in an AssTuple tree'''
- v = OpFinder()
- walk(node, v, verbose = 0)
- return v.op
-
-
- class OpFinder:
-
- def __init__(self):
- self.op = None
-
-
- def visitAssName(self, node):
- if self.op is None:
- self.op = node.flags
- elif self.op != node.flags:
- raise ValueError, 'mixed ops in stmt'
-
-
- visitAssAttr = visitAssName
- visitSubscript = visitAssName
-
-
- class Delegator:
- '''Base class to support delegation for augmented assignment nodes
-
- To generator code for augmented assignments, we use the following
- wrapper classes. In visitAugAssign, the left-hand expression node
- is visited twice. The first time the visit uses the normal method
- for that node . The second time the visit uses a different method
- that generates the appropriate code to perform the assignment.
- These delegator classes wrap the original AST nodes in order to
- support the variant visit methods.
- '''
-
- def __init__(self, obj):
- self.obj = obj
-
-
- def __getattr__(self, attr):
- return getattr(self.obj, attr)
-
-
-
- class AugGetattr(Delegator):
- pass
-
-
- class AugName(Delegator):
- pass
-
-
- class AugSlice(Delegator):
- pass
-
-
- class AugSubscript(Delegator):
- pass
-
- wrapper = {
- ast.Getattr: AugGetattr,
- ast.Name: AugName,
- ast.Slice: AugSlice,
- ast.Subscript: AugSubscript }
-
- def wrap_aug(node):
- return wrapper[node.__class__](node)
-
- if __name__ == '__main__':
- for file in sys.argv[1:]:
- compileFile(file)
-
-
-